import os,sys,getopt
import pygame.image,pygame.mixer,pygame.constants
from pygame.sprite import Group
from pygame.locals import HWSURFACE,RLEACCEL
from pygame.rect import Rect
from types import IntType

def parseArgs(opts):
    """ Parses argv with the opts and returns a dictionary with opt as key and argv as value
        and the remaining un parsed arguments in a tuple.
    """
    try:
        (args,args2) = getopt.getopt(sys.argv[1:],opts)
    except getopt.error,errormsg:
        message = 'Error: %s'%(errormsg),
        raise SystemExit, message

    # Convert args tuple to a dict
    argdict={}
    for arg in args:
        argdict[arg[0][1:]] = arg[1]
    return (argdict,args2)

def load_sound(name):
    if not pygame.mixer:
        return NoneSound()
    fullname = os.path.join('', name)
    try:
        sound = pygame.mixer.Sound(fullname)
    except pygame.error, message:
        print 'Cannot load sound:', fullname
        raise SystemExit, message
    return sound

def load_image(name, colorkey=None):
    fullname = os.path.join('', name)

    try:
        print 'load image:', name
        image = pygame.image.load(fullname)
    except pygame.error, message:
        print 'Cannot load image:', name
        raise SystemExit, message
    # ??????? Need to convert two times to get first tile image to become HW surface ??????????
    #image = image.convert()
    image = image.convert()
    if image.get_flags() & HWSURFACE == HWSURFACE:
        print 'Hardware Accelerated'
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey, RLEACCEL)
    return image

class Tick:
    def __init__(self,interval):
        self.tick_interval = interval
        self.tick_time = 0
        self.tick_flag = 0

    def isSet(self):
        return self.tick_flag
    
    def set(self):
        self.tick_flag = 1

    def tick(self,dt):
        self.tick_time += dt
        if self.tick_time > self.tick_interval:
            self.tick_flag = 1

    def reset(self):
        self.tick_time = 0
        self.tick_flag = 0

class BounderyVal:
    ' class that keeps a value insid min/max bounderys'
    def __init__(self,min,max,val):
        self.min = float(min)
        self.max = float(max)
        self.val = float(val)
        self.startval = val
        self.old_val = self.val
        self.changed = 0        
    def change(self,dval):
        self.old_val = self.val
        self.val +=dval
        return self.__keepBounds()
    def set(self,val):
        self.old_val = self.val
        self.val = val
        return self.__keepBounds()
    def reset(self):
        self.old_val = self.val
        self.val = self.startval
        return self.__keepBounds()

    def __keepBounds(self):
        self.val = max(self.min,min(self.max,self.val))
        return self.old_val != self.val
##        if self.val > self.max:
##            self.val = self.max
##        elif self.val < self.min:
##            self.val = self.min
##        if self.old_val == self.val:
##            self.changed = 0
##        else:
##            self.changed = 1
##        return self.changed

#----------------------------------------------------------------        

class ViewPort(Rect):
    'Extends Rect to provide a screen offset'
    id = 0
    def __init__(self,x,y,w,h,screen_pos , screen):
        self.screen_pos = screen_pos
        self.screen = screen.subsurface(screen_pos[0],screen_pos[1],w,h)
        Rect.__init__(self,x,y,w,h)
        self.id = self.__class__.id
        self.__class__.id += 1 

        # map screen methods to me
        self.fill = self.screen.fill
        self.blit = self.screen.blit

#----------------------------------------------------------------        
from operator import attrgetter
class RenderToViewPort(Group):
    ''' extends sprite group to draw sprites in a viewport
    '''
    def draw(self,viewport):
        """draw(surface)
           draw all sprites in the viewport onto a surface
        """
        dx = -viewport[0]
        dy = -viewport[1]
        b = viewport.blit
        get_image = attrgetter('image')
        get_rect = attrgetter('rect')
        for s in self.spritedict.keys():
            # Convert rect to screen cords before blitting
            b(get_image(s), get_rect(s).move(dx,dy))

#----------------------------------------------------------------        

class GameObjectGroup(Group):
    ' extended sprite group to allow use of interger id in has() and getById()'
    def __init__(self,gos=()):
        Group.__init__(self,gos)
        self.game_objects_id = {}
        for go in gos:
            self.game_objects_id[go.id] = go

    def add(self,gos):
        for go in gos:
            self.game_objects_id[go.id] = go
            Group.add(self,go)

    def add_internal(self, go):
        self.game_objects_id[go.id] = go
        Group.add_internal(self,go)

    def remove_internal(self, go):
        try:
            del self.game_objects_id[go.id]
        except KeyError:
            sys.stderr.write("Group has no sprite with id:%d\n"%go.id)
        Group.remove_internal(self,go)

    def remove(self,gos):
        for go in gos:
            try:
                del self.game_objects_id[go.id]
            except KeyError:
                sys.stderr.write("Group has no sprite with id:%d\n"%go.id)

        Group.remove(self,gos)

    def getById(self,id):
        return self.game_objects_id[id]

    def has(self,go):
        if type(go) is IntType:
            return self.game_objects_id.has_key(go)
        else:
            return Group.has(self,go)

from math import sqrt,hypot

class Vector2(object):
    
    __slots__ = ('_x', '_y')
    
    def __init__(self, x=0., y=0.):
        """Initialise a vector
        x -- The x value (defaults to 0.)
        y -- The y value (defaults to 0.)
        
        """
        self._x = float(x)
        self._y = float(y)
    
        
    @staticmethod
    def from_iterable(iterable):
        """Creates a Vector2 object from an iterable.
        iterable -- An iterable of at least 2 numeric values
        
        """
        it = iter(iterable)
        x = it.next()
        y = it.next()
        v = Vector2(x, y)        
        
    @staticmethod
    def from_points(p1, p2):
        """Creates a Vector2 object between two points.
        p1  -- First point
        p2 -- Second point
        
        """
        v = Vector2.__new__(Vector2, object)
        v._x = p2[0] - p1[0]
        v._y = p2[1] - p1[1]
        return v
    
    def copy(self):
        """Returns a copy of this object."""
        return Vector2(self._x, self._y)
        
    def get_x(self):
        return self._x
    def set_x(self, x):
        self._x = float(x)
    x = property(get_x, set_x, None, "x component.")
    
    def get_y(self):
        return self._y
    def set_y(self, y):
        self._y = float(y)
    y = property(get_y, set_y, None, "y component.")
        
    u = property(get_x, set_y, None, "u component (alias for x).")
    v = property(get_y, set_y, None, "v component (alias for y).")
        
    def __str__(self):
        
        return "( %s, %s )" % (self._x, self._y)
    
    def __repr__(self):
        
        return "Vector2(%s, %s)" % (self._x, self._y)
        
    def help(self):
        
        return "This is a Vector2 object used to represent direction and magnitude (length) or a position - in 2 dimensions"\
                "\n\tIts has the value %s\n\tIt is %s units long" % (self, self.get_length())        
                
    def __iter__(self):
        
        yield self._x
        yield self._y
        
    def __len__(self):
        
        return 2
    
    
    def __getitem__(self, index):
        """Gets a component as though the vector were a list."""
        try:            
            return getattr(self, self.__slots__[index])
        except IndexError:
            raise IndexError, "There are 2 values in this object, index should be 0 or 1!"
            
    def __setitem__(self, index, value):
        """Sets a component as though the vector were a list."""
        try:
            setattr( self, self.__slots__[index], value )            
        except IndexError:
            raise IndexError, "There are 2 values in this object, index should be 0 or 1!"
     
          
    def __add__(self, rhs):
        
        return Vector2(self._x+rhs[0], self._y+rhs[1])
        
        
    def __iadd__(self, rhs):
        
        self._x += rhs[0]
        self._y += rhs[1]
        return self
        
        
    def __sub__(self, rhs):
        
        return Vector2(self._x-rhs[0], self._y-rhs[1])
        
        
    def _isub__(self, rhs):
        
        self._x -= rhs[0]
        self._y -= rhs[1]
        return self
        
        
    def __mul__(self, rhs):
        """Return the result of multiplying this vector with a scalar or a vector-list object."""        
        if hasattr(rhs, "__getitem__"):
            return Vector2(self._x*rhs[0], self._y*rhs[1])
        else:
            return Vector2(self._x*rhs, self._y*rhs)
            
            
    def __rmul__(self, rhs):
        """Multiplys this vector with a scalar or a vector-list object.""" 
        if hasattr(rhs, "__getitem__"):
            self._x *= rhs[0]
            self._y *= rhs[1]            
        else:
            self._x *= rhs
            self._y *= rhs
        return self
        
        
    def __div__(self, rhs):
        """Return the result of dividing this vector by a scalar or a vector-list object."""        
        if hasattr(rhs, "__getitem__"):
            return Vector2(self._x/rhs[0], self._y/rhs[1])
        else:
            return Vector2(self._x/rhs, self._y/rhs)
            
            
    def __idiv__(self, rhs):
        """Divides this vector with a scalar or a vector-list object."""
        if hasattr(rhs, "__getitem__"):
            self._x /= rhs[0]
            self._y /= rhs[1]            
        else:
            self._x /= rhs
            self._y /= rhs
        return self
       
       
    def __neg__(self):
        """Return the negation of this vector."""
        return Vector2(-self._x, -self._y)
    
    def __call__(self, keys):
        """Used to swizzle a vector.
        keys -- A string containing a list of component names
        i.e. vec = Vector(1, 2)
        vec('yx') --> (2, 1)"""
        return tuple( getattr(self, "_"+key) for key in keys )


    def as_tuple(self):
        """Converts this vector to a tuple."""
        return (self._x, self._y)


    def get_length(self):
        """Returns the length of this vector."""
        return hypot(self._x,self._y)
        
    
    def get_magnitude(self):
        """Returns the length of this vector."""
        return hypot(self._x,self._y)
        
    
    def get_normalized(self):
        length = self.get_length()
        return Vector2(self._x / length, self._y / length)
    
    def normalise(self):
        """Normalises this vector."""
        length = self.get_length()
        if length:
            self._x /= length
            self._y /= length
            
    def normalize(self):
        """Normalises this vector."""
        length = self.get_length()
        if length:
            self._x /= length
            self._y /= length
        
    
    def get_distance(self, p):
        """Returns the distance to a point.
        
        p -- A Vector2 or list-like object with at least 2 values."""
        return sqrt( (self._x - p[0])**2 + (self._y - p[1])**2 );
        


if __name__ == "__main__":
    print Vector2(1,1).get_normalized()
    v1 = Vector2(1, 2)
    print v1('yx')
    